/**
  ******************************************************************************
  * @file    usbh_msc_scsi.c
  * @author  MCD Application Team
  * @version V2.1.0
  * @date    19-March-2012
  * @brief   This file implements the SCSI commands
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "usbh_msc_core.h"
#include "usbh_msc_scsi.h"
#include "usbh_msc_bot.h"
#include "usbh_ioreq.h"
#include "usbh_def.h"


/** @addtogroup USBH_LIB
  * @{
  */

/** @addtogroup USBH_CLASS
  * @{
  */

/** @addtogroup USBH_MSC_CLASS
  * @{
  */

/** @defgroup USBH_MSC_SCSI
  * @brief    This file includes the mass storage related functions
  * @{
  */


/** @defgroup USBH_MSC_SCSI_Private_TypesDefinitions
  * @{
  */

MassStorageParameter_TypeDef USBH_MSC_Param;
/**
  * @}
  */

/** @defgroup USBH_MSC_SCSI_Private_Defines
  * @{
  */
/**
  * @}
  */

/** @defgroup USBH_MSC_SCSI_Private_Macros
  * @{
  */
/**
  * @}
  */


/** @defgroup USBH_MSC_SCSI_Private_Variables
  * @{
  */

#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN uint8_t USBH_DataInBuffer[512] __ALIGN_END;

#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
#if defined ( __ICCARM__ ) /*!< IAR Compiler */
#pragma data_alignment=4
#endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN uint8_t USBH_DataOutBuffer[512] __ALIGN_END;
/**
  * @}
  */


/** @defgroup USBH_MSC_SCSI_Private_FunctionPrototypes
  * @{
  */
/**
  * @}
  */


/** @defgroup USBH_MSC_SCSI_Exported_Variables
  * @{
  */

/**
  * @}
  */


/** @defgroup USBH_MSC_SCSI_Private_Functions
  * @{
  */




/**
  * @brief  USBH_MSC_TestUnitReady
  *         Issues 'Test unit ready' command to the device. Once the response
  *         received, it updates the status to upper layer.
  * @param  None
  * @retval Status
  */
uint8_t USBH_MSC_TestUnitReady(USB_OTG_CORE_HANDLE *pdev)
{
    uint8_t index;
    USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;

    if(HCD_IsDeviceConnected(pdev))
    {
        switch(USBH_MSC_BOTXferParam.CmdStateMachine)
        {
            case CMD_SEND_STATE:
                /*Prepare the CBW and relevent field*/
                USBH_MSC_CBWData.field.CBWTransferLength = 0;       /* No Data Transfer */
                USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_OUT;
                USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH_TEST_UNIT_READY;
                USBH_MSC_BOTXferParam.pRxTxBuff = USBH_MSC_CSWData.CSWArray;
                USBH_MSC_BOTXferParam.DataLength = USBH_MSC_CSW_MAX_LENGTH;
                USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_TEST_UNIT_READY;

                for(index = CBW_CB_LENGTH; index != 0; index--)
                {
                    USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
                }

                USBH_MSC_CBWData.field.CBWCB[0]  = OPCODE_TEST_UNIT_READY;
                USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
                /* Start the transfer, then let the state
                machine magage the other transactions */
                USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
                USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
                USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
                status = USBH_MSC_BUSY;
                break;

            case CMD_WAIT_STATUS:
                if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
                {
                    /* Commands successfully sent and Response Received  */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_OK;
                }
                else if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL)
                {
                    /* Failure Mode */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_FAIL;
                }
                else if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR)
                {
                    /* Failure Mode */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_PHASE_ERROR;
                }

                break;

            default:
                break;
        }
    }

    return status;
}


/**
  * @brief  USBH_MSC_ReadCapacity10
  *         Issue the read capacity command to the device. Once the response
  *         received, it updates the status to upper layer
  * @param  None
  * @retval Status
  */
uint8_t USBH_MSC_ReadCapacity10(USB_OTG_CORE_HANDLE *pdev)
{
    uint8_t index;
    USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;

    if(HCD_IsDeviceConnected(pdev))
    {
        switch(USBH_MSC_BOTXferParam.CmdStateMachine)
        {
            case CMD_SEND_STATE:
                /*Prepare the CBW and relevent field*/
                USBH_MSC_CBWData.field.CBWTransferLength = XFER_LEN_READ_CAPACITY10;
                USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
                USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
                USBH_MSC_BOTXferParam.pRxTxBuff = USBH_DataInBuffer;
                USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_READ_CAPACITY10;

                for(index = CBW_CB_LENGTH; index != 0; index--)
                {
                    USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
                }

                USBH_MSC_CBWData.field.CBWCB[0]  = OPCODE_READ_CAPACITY10;
                USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
                /* Start the transfer, then let the state machine manage the other
                                                                          transactions */
                USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
                USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
                USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
                status = USBH_MSC_BUSY;
                break;

            case CMD_WAIT_STATUS:
                if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
                {
                    /*assign the capacity*/
                    (((uint8_t *)&USBH_MSC_Param.MSCapacity)[3]) = USBH_DataInBuffer[0];
                    (((uint8_t *)&USBH_MSC_Param.MSCapacity)[2]) = USBH_DataInBuffer[1];
                    (((uint8_t *)&USBH_MSC_Param.MSCapacity)[1]) = USBH_DataInBuffer[2];
                    (((uint8_t *)&USBH_MSC_Param.MSCapacity)[0]) = USBH_DataInBuffer[3];
                    /*assign the page length*/
                    (((uint8_t *)&USBH_MSC_Param.MSPageLength)[1]) = USBH_DataInBuffer[6];
                    (((uint8_t *)&USBH_MSC_Param.MSPageLength)[0]) = USBH_DataInBuffer[7];
                    /* Commands successfully sent and Response Received  */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_OK;
                }
                else if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL)
                {
                    /* Failure Mode */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_FAIL;
                }
                else if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR)
                {
                    /* Failure Mode */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_PHASE_ERROR;
                }
                else
                {
                    /* Wait for the Commands to get Completed */
                    /* NO Change in state Machine */
                }

                break;

            default:
                break;
        }
    }

    return status;
}


/**
  * @brief  USBH_MSC_ModeSense6
  *         Issue the Mode Sense6 Command to the device. This function is used
  *          for reading the WriteProtect Status of the Mass-Storage device.
  * @param  None
  * @retval Status
  */
uint8_t USBH_MSC_ModeSense6(USB_OTG_CORE_HANDLE *pdev)
{
    uint8_t index;
    USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;

    if(HCD_IsDeviceConnected(pdev))
    {
        switch(USBH_MSC_BOTXferParam.CmdStateMachine)
        {
            case CMD_SEND_STATE:
                /*Prepare the CBW and relevent field*/
                USBH_MSC_CBWData.field.CBWTransferLength = XFER_LEN_MODE_SENSE6;
                USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
                USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
                USBH_MSC_BOTXferParam.pRxTxBuff = USBH_DataInBuffer;
                USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_MODE_SENSE6;

                for(index = CBW_CB_LENGTH; index != 0; index--)
                {
                    USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
                }

                USBH_MSC_CBWData.field.CBWCB[0]  = OPCODE_MODE_SENSE6;
                USBH_MSC_CBWData.field.CBWCB[2]  = MODE_SENSE_PAGE_CONTROL_FIELD | \
                                                   MODE_SENSE_PAGE_CODE;
                USBH_MSC_CBWData.field.CBWCB[4]  = XFER_LEN_MODE_SENSE6;
                USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
                /* Start the transfer, then let the state machine manage the other
                                                                          transactions */
                USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
                USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
                USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
                status = USBH_MSC_BUSY;
                break;

            case CMD_WAIT_STATUS:
                if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
                {
                    /* Assign the Write Protect status */
                    /* If WriteProtect = 0, Writing is allowed
                       If WriteProtect != 0, Disk is Write Protected */
                    if(USBH_DataInBuffer[2] & MASK_MODE_SENSE_WRITE_PROTECT)
                    {
                        USBH_MSC_Param.MSWriteProtect   = DISK_WRITE_PROTECTED;
                    }
                    else
                    {
                        USBH_MSC_Param.MSWriteProtect   = 0;
                    }

                    /* Commands successfully sent and Response Received  */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_OK;
                }
                else if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL)
                {
                    /* Failure Mode */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_FAIL;
                }
                else if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR)
                {
                    /* Failure Mode */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_PHASE_ERROR;
                }
                else
                {
                    /* Wait for the Commands to get Completed */
                    /* NO Change in state Machine */
                }

                break;

            default:
                break;
        }
    }

    return status;
}

/**
  * @brief  USBH_MSC_RequestSense
  *         Issues the Request Sense command to the device. Once the response
  *         received, it updates the status to upper layer
  * @param  None
  * @retval Status
  */
uint8_t USBH_MSC_RequestSense(USB_OTG_CORE_HANDLE *pdev)
{
    USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
    uint8_t index;

    if(HCD_IsDeviceConnected(pdev))
    {
        switch(USBH_MSC_BOTXferParam.CmdStateMachine)
        {
            case CMD_SEND_STATE:
                /*Prepare the CBW and relevent field*/
                USBH_MSC_CBWData.field.CBWTransferLength = \
                        ALLOCATION_LENGTH_REQUEST_SENSE;
                USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
                USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
                USBH_MSC_BOTXferParam.pRxTxBuff = USBH_DataInBuffer;
                USBH_MSC_BOTXferParam.MSCStateBkp = USBH_MSC_BOTXferParam.MSCStateCurrent;
                USBH_MSC_BOTXferParam.MSCStateCurrent = USBH_MSC_REQUEST_SENSE;

                for(index = CBW_CB_LENGTH; index != 0; index--)
                {
                    USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
                }

                USBH_MSC_CBWData.field.CBWCB[0]  = OPCODE_REQUEST_SENSE;
                USBH_MSC_CBWData.field.CBWCB[1]  = DESC_REQUEST_SENSE;
                USBH_MSC_CBWData.field.CBWCB[4]  = ALLOCATION_LENGTH_REQUEST_SENSE;
                USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
                /* Start the transfer, then let the state machine magage
                the other transactions */
                USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
                USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
                USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
                status = USBH_MSC_BUSY;
                break;

            case CMD_WAIT_STATUS:
                if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
                {
                    /* Get Sense data*/
                    (((uint8_t *)&USBH_MSC_Param.MSSenseKey)[3]) = USBH_DataInBuffer[0];
                    (((uint8_t *)&USBH_MSC_Param.MSSenseKey)[2]) = USBH_DataInBuffer[1];
                    (((uint8_t *)&USBH_MSC_Param.MSSenseKey)[1]) = USBH_DataInBuffer[2];
                    (((uint8_t *)&USBH_MSC_Param.MSSenseKey)[0]) = USBH_DataInBuffer[3];
                    /* Commands successfully sent and Response Received  */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_OK;
                }
                else if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL)
                {
                    /* Failure Mode */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_FAIL;
                }
                else if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR)
                {
                    /* Failure Mode */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_PHASE_ERROR;
                }
                else
                {
                    /* Wait for the Commands to get Completed */
                    /* NO Change in state Machine */
                }

                break;

            default:
                break;
        }
    }

    return status;
}


/**
  * @brief  USBH_MSC_Write10
  *         Issue the write command to the device. Once the response received,
  *         it updates the status to upper layer
  * @param  dataBuffer : DataBuffer contains the data to write
  * @param  address : Address to which the data will be written
  * @param  nbOfbytes : NbOfbytes to be written
  * @retval Status
  */
uint8_t USBH_MSC_Write10(USB_OTG_CORE_HANDLE *pdev,
                         uint8_t *dataBuffer,
                         uint32_t address,
                         uint32_t nbOfbytes)
{
    uint8_t index;
    USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
    uint16_t nbOfPages;

    if(HCD_IsDeviceConnected(pdev))
    {
        switch(USBH_MSC_BOTXferParam.CmdStateMachine)
        {
            case CMD_SEND_STATE:
                USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes;
                USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_OUT;
                USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
                USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer;

                for(index = CBW_CB_LENGTH; index != 0; index--)
                {
                    USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
                }

                USBH_MSC_CBWData.field.CBWCB[0]  = OPCODE_WRITE10;
                /*logical block address*/
                USBH_MSC_CBWData.field.CBWCB[2]  = (((uint8_t *)&address)[3]);
                USBH_MSC_CBWData.field.CBWCB[3]  = (((uint8_t *)&address)[2]);
                USBH_MSC_CBWData.field.CBWCB[4]  = (((uint8_t *)&address)[1]);
                USBH_MSC_CBWData.field.CBWCB[5]  = (((uint8_t *)&address)[0]);
                /*USBH_MSC_PAGE_LENGTH = 512*/
                nbOfPages = nbOfbytes / USBH_MSC_PAGE_LENGTH;
                /*Tranfer length */
                USBH_MSC_CBWData.field.CBWCB[7]  = (((uint8_t *)&nbOfPages)[1]);
                USBH_MSC_CBWData.field.CBWCB[8]  = (((uint8_t *)&nbOfPages)[0]);
                USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
                /* Start the transfer, then let the state machine
                magage the other transactions */
                USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
                USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
                USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
                status = USBH_MSC_BUSY;
                break;

            case CMD_WAIT_STATUS:
                if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK)
                {
                    /* Commands successfully sent and Response Received  */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_OK;
                }
                else if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL)
                {
                    /* Failure Mode */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                }
                else if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR)
                {
                    /* Failure Mode */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_PHASE_ERROR;
                }

                break;

            default:
                break;
        }
    }

    return status;
}

/**
  * @brief  USBH_MSC_Read10
  *         Issue the read command to the device. Once the response received,
  *         it updates the status to upper layer
  * @param  dataBuffer : DataBuffer will contain the data to be read
  * @param  address : Address from which the data will be read
  * @param  nbOfbytes : NbOfbytes to be read
  * @retval Status
  */
uint8_t USBH_MSC_Read10(USB_OTG_CORE_HANDLE *pdev,
                        uint8_t *dataBuffer,
                        uint32_t address,
                        uint32_t nbOfbytes)
{
    uint8_t index;
    static USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
    uint16_t nbOfPages;
    status = USBH_MSC_BUSY;

    if(HCD_IsDeviceConnected(pdev))
    {
        switch(USBH_MSC_BOTXferParam.CmdStateMachine)
        {
            case CMD_SEND_STATE:
                /*Prepare the CBW and relevent field*/
                USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes;
                USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
                USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
                USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer;

                for(index = CBW_CB_LENGTH; index != 0; index--)
                {
                    USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
                }

                USBH_MSC_CBWData.field.CBWCB[0]  = OPCODE_READ10;
                /*logical block address*/
                USBH_MSC_CBWData.field.CBWCB[2]  = (((uint8_t *)&address)[3]);
                USBH_MSC_CBWData.field.CBWCB[3]  = (((uint8_t *)&address)[2]);
                USBH_MSC_CBWData.field.CBWCB[4]  = (((uint8_t *)&address)[1]);
                USBH_MSC_CBWData.field.CBWCB[5]  = (((uint8_t *)&address)[0]);
                /*USBH_MSC_PAGE_LENGTH = 512*/
                nbOfPages = nbOfbytes / USBH_MSC_PAGE_LENGTH;
                /*Tranfer length */
                USBH_MSC_CBWData.field.CBWCB[7]  = (((uint8_t *)&nbOfPages)[1]);
                USBH_MSC_CBWData.field.CBWCB[8]  = (((uint8_t *)&nbOfPages)[0]);
                USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
                /* Start the transfer, then let the state machine
                magage the other transactions */
                USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
                USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
                USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
                status = USBH_MSC_BUSY;
                break;

            case CMD_WAIT_STATUS:
                if((USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK) && \
                        (HCD_IsDeviceConnected(pdev)))
                {
                    /* Commands successfully sent and Response Received  */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_OK;
                }
                else if((USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL) && \
                        (HCD_IsDeviceConnected(pdev)))
                {
                    /* Failure Mode */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                }
                else if(USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR)
                {
                    /* Failure Mode */
                    USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
                    status = USBH_MSC_PHASE_ERROR;
                }
                else
                {
                    /* Wait for the Commands to get Completed */
                    /* NO Change in state Machine */
                }

                break;

            default:
                break;
        }
    }

    return status;
}


/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/



